﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WorkStation.UI.Controls
{
    public partial class MotionBoard : UserControl
    {
        public string Description;
        public int _marginLeft = 60;
        public int _marginRight = 40;
        public int _marginUp = 40;
        public int _marginDown = 40;
        public int _gridCellWidth = 10;
        public int _gridCellHeight = 10;
        public int _rowCount;
        public int _colCount;
        public int _totalWidth;
        public int _totalHeight;
        public List<MotionShape> CreatedShapes;
        private RectangleMotion _workArea;
        public List<MotionPoint> MotionPoints;
        private MotionCoordinate _crdX;
        public MotionCoordinate CoordinateX 
        {
            get { return _crdX; }
            set { _crdX = value; }
        }
        private MotionCoordinate _crdY;
        public MotionCoordinate CoordinateY
        {
            get { return _crdY; }
            set { _crdY = value; }
        }
                
        private MotionCoordinate _crdR;
        public MotionCoordinate CoordinateR
        {
            get { return _crdR; }
            set { _crdR = value; }
        }
        private MotionTable _table;
        private List<MotionLimitRectangle> _limitRects;
        private List<MotionDirectRectangle> _directRects;
        public MotionTable Table
        {
            get { return _table; }
            set { _table = value; }
        }
        private MotionInfo _info;
        private RectangleMotion _outRect;
        private RectangleMotion _inRect;
        /// <summary>
        /// 拖拽移动图片起始点
        /// </summary>
        private PointF _dragStartPoint = new PointF(0, 0);
        private Color _displayerBackColor = Color.White;
        public Color DisplayerBackColor
        {
            get
            {
                return _displayerBackColor;
            }
            set
            {
                _displayerBackColor = value;
            }
        }
        private bool _isDisplayExample;
        public bool IsDisplayerExample
        {
            set 
            { 
                _isDisplayExample = value;
                l_Example.Visible = _isDisplayExample;
            }
        }

        /// <summary>
        /// 图片起始X位置
        /// </summary>
        private float _originX;
        public float OriginX
        {
            get { return _originX; }
            set
            {
                _originX = value;
            }
        }
        /// <summary>
        /// 图片起始Y位置
        /// </summary>
        private float _originY;
        public float OriginY
        {
            get { return _originY; }
            set
            {
                _originY = value;
            }
        }
        public bool SimpleMode;
        public Action<double, double, double, double, double, double, double, double> NotifyBoardScale;
        public Action<MotionBoard, MotionPoint> NotifyCreatePointRequest;
        public Action<string, RectDirection> NotifyDirectRectMouseDown;
        public Action<string> NotifyDirectRectMouseUp;
        public Action<string> NotifyStopClick;
        public Action<MotionBoard, string, double, double, double> OnGoToBoardPoint;
        public Action<MotionBoard> OnKeyboardEnableClick;
        public MotionBoard(string name)
        {
            InitializeComponent();
            this.MouseWheel += MotionBoard_MouseWheel;
            this.MotionPoints = new List<MotionPoint>();
            this.CreatedShapes = new List<MotionShape>();
            this._limitRects = new List<MotionLimitRectangle>();
            this._directRects = new List<MotionDirectRectangle>();
            this.Description = name;
        }
        private void MotionBoard_MouseWheel(object sender, MouseEventArgs e)
        {
            if (!SimpleMode)
            {
                if (e.Delta > 0)
                    TestZoom(e.X, e.Y, true);
                if (e.Delta < 0)
                    TestZoom(e.X, e.Y, false);
                this.Repaint();
            }
            if (_crdX != null && _crdY != null && NotifyBoardScale != null)
            {
                NotifyBoardScale(_crdX.ShowNegative, _crdX.ShowPositive, _crdX.NegativeLimit, _crdX.PositiveLimit,
                                 _crdY.ShowNegative, _crdY.ShowPositive, _crdY.NegativeLimit, _crdY.PositiveLimit);
            }
        }
        private void onBoardSizeChanged()
        {
            this._rowCount = (this.Height - this._marginUp - this._marginDown) / this._gridCellHeight;
            this._colCount = (this.Width - this._marginLeft - this._marginRight) / this._gridCellWidth;
            this._totalWidth = this._colCount * this._gridCellWidth;
            this._totalHeight = this._rowCount * this._gridCellHeight;
        }
        public void UpdateBoard()
        {
            if (_crdX != null)
            {
                _crdX.Update(this._totalWidth, this._totalHeight, this._marginLeft, this._marginUp);
            }
            if (_crdY != null)
            {
                _crdY.Update(this._totalWidth, this._totalHeight, this._marginLeft, this._marginUp);
            }
            if (_crdR != null)
            {
                _crdR.Update(this._totalWidth, this._totalHeight, this._marginLeft, this._marginUp);
            }
            if (_info == null)
                _info = new MotionInfo(this.CreatedShapes);
            if (_workArea == null)
            {
                //增加作业区域
                _workArea = new RectangleMotion();
                _workArea.IsFill = true;
                _workArea.Alpha = 100;
                _workArea.FillColor = Color.LightGray;
                this.CreatedShapes.Add(_workArea);
            }
            _workArea.StartPoint = new Point(this._marginLeft, this._marginUp);
            _workArea.EndPoint = new PointF(this._marginLeft + this._totalWidth, this._marginUp + this._totalHeight);
            if (_table != null)
            {
                //_table.XPosition = 100;
                //_table.YPosition = 200;
                //_table.RPosition = 30;
                _table.Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp);
            }
            if(_limitRects != null && _limitRects.Count > 0)
            {
                for (int i = 0; i < _limitRects.Count; i++)
                {
                    _limitRects[i].Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp);
                }
            }
            if (_directRects != null && _directRects.Count > 0)
            {
                for (int i = 0; i < _directRects.Count; i++)
                {
                    _directRects[i].Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp);
                }
            }
            if (_isDisplayExample)
            {
                this.l_Example.Location = new Point(_marginLeft + _totalWidth - this.l_Example.Width - 10, _marginUp + _totalHeight - this.l_Example.Height - 10) ;
            }
        }
        private void updateBoard2()
        {
            if(_outRect == null)
            {
                _outRect = new RectangleMotion("outRect");
                _outRect.PaintColor = Color.Black;
                _outRect.LineWidth = 1;
                this.CreatedShapes.Add(_outRect);
            }
            _outRect.StartPoint = new Point(this._marginLeft, this._marginUp);
            _outRect.EndPoint = new PointF(this._marginLeft + this._totalWidth, this._marginUp + this._totalHeight);
            if (_inRect == null)
            {
                _inRect = new RectangleMotion("inRect");
                _inRect.PaintColor = Color.Blue;
                _inRect.IsFill = true;
                _inRect.Alpha = 40;
                _inRect.FillColor = Color.LimeGreen;
                _inRect.LineWidth = 1;
                _inRect.StartPoint = new Point(this._marginLeft, this._marginUp);
                _inRect.EndPoint = new PointF(this._marginLeft + this._totalWidth, this._marginUp + this._totalHeight);
                this.CreatedShapes.Add(_inRect);
            }
            if(_isDisplayExample)
            {
                this.l_Example.Location = new Point(_marginLeft + _totalWidth - this.l_Example.Width, _marginUp + _totalHeight - this.l_Example.Height);
            }
        }
        public void UpdateTable()
        {
            _table.Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp);
        }
        public void CreateCoordinate(string crdType, AxisDir direction, AxisLocation location, double negativeLimit, double positiveLimit)
        {
            switch(crdType)
            {
                case "X":
                    _crdX = new MotionCoordinate("X", this.CreatedShapes);
                    _crdX.PaintColor = Color.LimeGreen;
                    _crdX.Direction = direction;
                    _crdX.Location = location;
                    _crdX.NegativeLimit = negativeLimit;
                    _crdX.PositiveLimit = positiveLimit;
                    _crdX.ShowNegative = negativeLimit;
                    _crdX.ShowPositive = positiveLimit;
                    this.l_Example.Text += "X:\r\n";
                    break;
                case "Y":
                    _crdY = new MotionCoordinate("Y", this.CreatedShapes);
                    _crdY.PaintColor = Color.Red;
                    _crdY.Direction = direction;
                    _crdY.Location = location;
                    _crdY.NegativeLimit = negativeLimit;
                    _crdY.PositiveLimit = positiveLimit;
                    _crdY.ShowNegative = negativeLimit;
                    _crdY.ShowPositive = positiveLimit;
                    this.l_Example.Text += "Y:\r\n";
                    break;
                case "Z":
                    _crdY = new MotionCoordinate("Z", this.CreatedShapes);
                    _crdY.PaintColor = Color.Blue;
                    _crdY.Direction = direction;
                    _crdY.Location = location;
                    _crdY.NegativeLimit = negativeLimit;
                    _crdY.PositiveLimit = positiveLimit;
                    _crdY.ShowNegative = negativeLimit;
                    _crdY.ShowPositive = positiveLimit;
                    this.l_Example.Text += "Z:\r\n";
                    break;
                case "R":
                    _crdR = new MotionCoordinate("R", this.CreatedShapes);
                    _crdR.Direction = direction;
                    _crdR.Location = location;
                    _crdR.NegativeLimit = negativeLimit;
                    _crdR.PositiveLimit = positiveLimit;
                    _crdR.ShowNegative = negativeLimit;
                    _crdR.ShowPositive = positiveLimit;
                    this.l_Example.Text += "R:\r\n";
                    break;
            }
        }
        public void CreateTable()
        {
            _table = new MotionTable("table", CreatedShapes);
        }
        public void CreateLimitArea(string name, double startX, double startY, double endX, double endY)
        {
            MotionLimitRectangle rect = new MotionLimitRectangle(name, this.CreatedShapes);
            rect.XLowPosition = startX;
            rect.XHighPosition = endX;
            rect.YLowPosition = startY;
            rect.YHighPosition = endY;
            this._limitRects.Add(rect);
        }
        public void CreateDirectionRect(string name)
        {
            MotionDirectRectangle rect = new MotionDirectRectangle(name, this.CreatedShapes);
            this._directRects.Add(rect);
        }
        public void ClearAll()
        {
            this.CreatedShapes.Clear();
            this._crdX = new MotionCoordinate("", null);
            this._crdX = null;
            this._crdY = new MotionCoordinate("", null);
            this._crdY = null;
            this._crdR = new MotionCoordinate("", null);
            this._crdR = null;
            this._table = new MotionTable("", null);
            this._table = null;
            this._workArea = null;
            this.l_Example.Text = "";
            this._info.Clear();
        }
        public void Repaint()
        {
            this.BeginInvoke(new Action(() =>
            {
                //this.pB_Displayer.Focus();
                this.pB_Displayer.Invalidate();
            }));
        }
        double zoomFactorNow = 1;
        public void TestZoom(int x, int y, bool inorout)
        {
            zoomFactorNow = inorout ? 1.05 : 0.95;
            if (_crdX != null)
            {
                double fixedPointX = 0;
                PointF p = new PointF();
                _crdX.GetActualPosition(x, y, _marginLeft, _marginUp, _totalWidth, _totalHeight, out fixedPointX, out p);
                double newNeg = fixedPointX - (fixedPointX - _crdX.ShowNegative) / zoomFactorNow;
                double newPos = fixedPointX + (_crdX.ShowPositive - fixedPointX) / zoomFactorNow;
                if (newNeg < _crdX.NegativeLimit)
                {
                    _crdX.ShowNegative = _crdX.NegativeLimit;
                    if ((_crdX.ShowPositive - _crdX.NegativeLimit) / zoomFactorNow + _crdX.NegativeLimit < _crdX.PositiveLimit)
                        _crdX.ShowPositive = (_crdX.ShowPositive - _crdX.NegativeLimit) / zoomFactorNow + _crdX.NegativeLimit;
                    else
                        _crdX.ShowPositive = _crdX.PositiveLimit;
                }
                else if (newPos > _crdX.PositiveLimit)
                {
                    _crdX.ShowPositive = _crdX.PositiveLimit;
                    if (_crdX.PositiveLimit - (_crdX.PositiveLimit - _crdX.ShowNegative) / zoomFactorNow > _crdX.NegativeLimit)
                        _crdX.ShowNegative = _crdX.PositiveLimit - (_crdX.PositiveLimit - _crdX.ShowNegative) / zoomFactorNow;
                    else
                        _crdX.ShowNegative = _crdX.NegativeLimit;
                }
                else
                {
                    _crdX.ShowNegative = newNeg;
                    _crdX.ShowPositive = newPos;
                }
                if (_crdX.ShowPositive <= _crdX.ShowNegative)
                {

                }
                _crdX.Update(_totalWidth, _totalHeight, _marginLeft, _marginUp, true);
            }
            if (_crdY != null)
            {
                double fixedPointY = 0;
                PointF p = new PointF();
                _crdY.GetActualPosition(x, y, _marginLeft, _marginUp, _totalWidth, _totalHeight, out fixedPointY, out p);
                double newNeg2 = fixedPointY - (fixedPointY - _crdY.ShowNegative) / zoomFactorNow;
                double newPos2 = fixedPointY + (_crdY.ShowPositive - fixedPointY) / zoomFactorNow;
                if (newNeg2 < _crdY.NegativeLimit)
                {
                    _crdY.ShowNegative = _crdY.NegativeLimit;
                    if ((_crdY.ShowPositive - _crdY.NegativeLimit) / zoomFactorNow + _crdY.NegativeLimit < _crdY.PositiveLimit)
                        _crdY.ShowPositive = (_crdY.ShowPositive - _crdY.NegativeLimit) / zoomFactorNow + _crdY.NegativeLimit;
                    else
                        _crdY.ShowPositive = _crdY.PositiveLimit;
                }
                else if (newPos2 > _crdY.PositiveLimit)
                {
                    _crdY.ShowPositive = _crdY.PositiveLimit;
                    if (_crdY.PositiveLimit - (_crdY.PositiveLimit - _crdY.ShowNegative) / zoomFactorNow > _crdY.NegativeLimit)
                        _crdY.ShowNegative = _crdY.PositiveLimit - (_crdY.PositiveLimit - _crdY.ShowNegative) / zoomFactorNow;
                    else
                        _crdY.ShowNegative = _crdY.NegativeLimit;
                }
                else
                {
                    _crdY.ShowNegative = newNeg2;
                    _crdY.ShowPositive = newPos2;
                }
                if (_crdY.ShowPositive <= _crdY.ShowNegative)
                {

                }
                _crdY.Update(_totalWidth, _totalHeight, _marginLeft, _marginUp, true);
            }
            if(_table != null)
                _table.Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp);
            if (_limitRects != null && _limitRects.Count > 0)
            {
                for (int i = 0; i < _limitRects.Count; i++)
                {
                    _limitRects[i].Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp);
                }
            }
            if (_directRects != null && _directRects.Count > 0)
            {
                for (int i = 0; i < _directRects.Count; i++)
                {
                    _directRects[i].Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp);
                }
            }
            //if(MotionPoints != null && MotionPoints.Count > 0)
            //{
            //    for (int i = 0; i < MotionPoints.Count; i++)
            //    {
            //        double xBoardPos = _marginLeft;
            //        double yBoardPos = _marginUp;
            //        double rBoardPos = 0;
            //        double rPos2 = 0;
            //        if (_crdX != null)
            //            _crdX.GetBoardPosition(MotionPoints[i].OriginPoint[0], _totalWidth, _totalHeight, _marginLeft, _marginUp, _crdX.Direction, out xBoardPos, out rPos2);
            //        if (_crdY != null)
            //            _crdY.GetBoardPosition(MotionPoints[i].OriginPoint[1], _totalWidth, _totalHeight, _marginLeft, _marginUp, _crdY.Direction, out yBoardPos, out rPos2);
            //        if (_crdR != null)
            //            _crdR.GetBoardPosition(MotionPoints[i].OriginPoint[2], _totalWidth, _totalHeight, _marginLeft, _marginUp, _crdR.Direction, out rBoardPos, out rPos2);
            //        if(_crdR != null)
            //            MotionPoints[i].CenterPoint = new PointF((float)rBoardPos, (float)rPos2);
            //        else
            //            MotionPoints[i].CenterPoint = new PointF((float)xBoardPos, (float)yBoardPos);
            //    }
            //}
        }
        bool rectClicked = false;
        private void pB_Displayer_MouseDown(object sender, MouseEventArgs e)
        {
            _dragStartPoint = new PointF(e.X, e.Y);
            _startDrag = true;
            double xpos = 0;
            double ypos = 0;
            double rpos = 0;
            PointF p = new PointF();
            if (_crdR != null)
            {
                _crdR.GetActualPosition(e.X, e.Y, _marginLeft, _marginUp, _totalWidth, _totalHeight, out rpos, out p);
                foreach (MotionPoint mp in MotionPoints)
                {
                    if (mp.PointOnShape2(rpos) == PositionOnShape.In)
                        mp.IsSelected = true;
                    else
                        mp.IsSelected = false;
                }
                foreach (var item in this._directRects)
                {
                    RectDirection dir = item.PointOnDirectionRect(_crdX, _crdY, _crdR, e.X, e.Y);
                    if (dir != RectDirection.Out)
                    {
                        switch (dir)
                        {
                            case RectDirection.Left:
                                item.Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp, isSelectedLeft: true);
                                break;
                            case RectDirection.Right:
                                item.Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp, isSelectedRight: true);
                                break;
                        }
                        rectClicked = true;
                        if (NotifyDirectRectMouseDown != null)
                            NotifyDirectRectMouseDown(Description, dir);
                    }
                }
            }
            else
            {
                if (_crdX != null)
                    _crdX.GetActualPosition(e.X, e.Y, _marginLeft, _marginUp, _totalWidth, _totalHeight, out xpos, out p);
                if (_crdY != null)
                    _crdY.GetActualPosition(e.X, e.Y, _marginLeft, _marginUp, _totalWidth, _totalHeight, out ypos, out p);
                if(_crdY != null && _crdX == null)
                {
                    foreach (var item in this._directRects)
                    {
                        RectDirection dir = item.PointOnDirectionRect(_crdX, _crdY, _crdR, e.X, e.Y);
                        if (dir != RectDirection.Out)
                        {
                            switch (dir)
                            {
                                case RectDirection.Up:
                                    item.Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp, isSelectedUp: true);
                                    break;
                                case RectDirection.Down:
                                    item.Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp, isSelectedDown: true);
                                    break;
                            }
                            rectClicked = true;
                            if (NotifyDirectRectMouseDown != null)
                                NotifyDirectRectMouseDown(Description, dir);
                        }
                    }
                }
                if (_crdY == null && _crdX != null)
                {
                    foreach (var item in this._directRects)
                    {
                        RectDirection dir = item.PointOnDirectionRect(_crdX, _crdY, _crdR, e.X, e.Y);
                        if (dir != RectDirection.Out)
                        {
                            switch (dir)
                            {
                                case RectDirection.Left:
                                    item.Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp, isSelectedLeft: true);
                                    break;
                                case RectDirection.Right:
                                    item.Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp, isSelectedRight: true);
                                    break;
                            }
                            rectClicked = true;
                            if (NotifyDirectRectMouseDown != null)
                                NotifyDirectRectMouseDown(Description, dir);
                        }
                    }
                }
                if (_crdX != null && _crdY != null)
                {
                    foreach (var item in this._directRects)
                    {
                        RectDirection dir = item.PointOnDirectionRect(_crdX, _crdY, _crdR, e.X, e.Y);
                        if (dir != RectDirection.Out)
                        {
                            switch (dir)
                            {
                                case RectDirection.Left:
                                    item.Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp, isSelectedLeft: true);
                                    break;
                                case RectDirection.Right:
                                    item.Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp, isSelectedRight: true);
                                    break;
                                case RectDirection.Up:
                                    item.Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp, isSelectedUp: true);
                                    break;
                                case RectDirection.Down:
                                    item.Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp, isSelectedDown: true);
                                    break;
                            }
                            rectClicked = true;
                            if (NotifyDirectRectMouseDown != null)
                                NotifyDirectRectMouseDown(Description, dir);
                        }
                    }
                }
                foreach (MotionPoint mp in MotionPoints)
                {
                    if (mp.PointOnShape(new PointF((float)xpos, (float)ypos)) == PositionOnShape.In)
                        mp.IsSelected = true;
                    else
                        mp.IsSelected = false;
                }
            }
            this.Repaint();
        }
        bool _startDrag = false;
        double _curActPosX;
        double _curActPosY;
        double _curActPosR;
        private void pB_Displayer_MouseMove(object sender, MouseEventArgs e)
        {
            PointF p = new PointF();
            if (_crdX != null)
                _crdX.GetActualPosition(e.X, e.Y, _marginLeft, _marginUp, _totalWidth, _totalHeight, out _curActPosX, out p);
            if (_crdY != null)
                _crdY.GetActualPosition(e.X, e.Y, _marginLeft, _marginUp, _totalWidth, _totalHeight, out _curActPosY, out p);
            if (_crdR != null)
                _crdR.GetActualPosition(e.X, e.Y, _marginLeft, _marginUp, _totalWidth, _totalHeight, out _curActPosR, out p);
            
            if (e.Button == MouseButtons.Left)
            {
                if (_startDrag && !SimpleMode)
                {
                    if (_crdX != null)
                    {
                        double nowX = 0;
                        _crdX.GetActualPosition(e.X, e.Y, _marginLeft, _marginUp, _totalWidth, _totalHeight, out _curActPosX, out p);
                        _crdX.GetActualPosition((int)_dragStartPoint.X, (int)_dragStartPoint.Y, _marginLeft, _marginUp, _totalWidth, _totalHeight, out nowX, out p);
                        double dragOffsetX = _curActPosX - nowX;
                        if (_crdX.ShowNegative - dragOffsetX <= _crdX.NegativeLimit)
                        {
                            _crdX.ShowNegative = _crdX.NegativeLimit;
                            _crdX.ShowPositive -= (_crdX.ShowNegative - _crdX.NegativeLimit);
                        }
                        else if (_crdX.ShowPositive - dragOffsetX >= _crdX.PositiveLimit)
                        {
                            _crdX.ShowPositive = _crdX.PositiveLimit;
                            _crdX.ShowNegative = _crdX.ShowNegative + (_crdX.PositiveLimit - _crdX.ShowPositive);
                        }
                        else
                        {
                            _crdX.ShowNegative -= dragOffsetX;
                            _crdX.ShowPositive -= dragOffsetX;
                        }
                        _crdX.Update(_totalWidth, _totalHeight, _marginLeft, _marginUp, true);
                        _dragStartPoint.X = e.X;
                    }
                    if (_crdY != null)
                    {
                        double nowY = 0;
                        _crdY.GetActualPosition(e.X, e.Y, _marginLeft, _marginUp, _totalWidth, _totalHeight, out _curActPosY, out p);
                        _crdY.GetActualPosition((int)_dragStartPoint.X, (int)_dragStartPoint.Y, _marginLeft, _marginUp, _totalWidth, _totalHeight, out nowY, out p);
                        double dragOffsetY = _curActPosY - nowY;
                        if (_crdY.ShowNegative - dragOffsetY <= _crdY.NegativeLimit)
                        {
                            _crdY.ShowNegative = _crdY.NegativeLimit;
                            _crdY.ShowPositive -= (_crdY.ShowNegative - _crdY.NegativeLimit);
                        }
                        else if (_crdY.ShowPositive - dragOffsetY >= _crdY.PositiveLimit)
                        {
                            _crdY.ShowPositive = _crdY.PositiveLimit;
                            _crdY.ShowNegative = _crdY.ShowNegative + (_crdY.PositiveLimit - _crdY.ShowPositive);
                        }
                        else
                        {
                            _crdY.ShowNegative -= dragOffsetY;
                            _crdY.ShowPositive -= dragOffsetY;
                        }
                        _crdY.Update(_totalWidth, _totalHeight, _marginLeft, _marginUp, true);
                        _dragStartPoint.Y = e.Y;
                    }
                    if(_table != null)
                        _table.Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp);
                    if (_limitRects != null && _limitRects.Count > 0)
                    {
                        for (int i = 0; i < _limitRects.Count; i++)
                        {
                            _limitRects[i].Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp);
                        }
                    }
                    if (_directRects != null && _directRects.Count > 0)
                    {
                        for (int i = 0; i < _directRects.Count; i++)
                        {
                            _directRects[i].Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp);
                        }
                    }
                    if (_crdX != null || _crdY != null || _table != null)
                        this.Repaint();
                    if (_crdX != null && _crdY != null && NotifyBoardScale != null)
                        NotifyBoardScale(_crdX.ShowNegative, _crdX.ShowPositive, _crdX.NegativeLimit, _crdX.PositiveLimit,
                                         _crdY.ShowNegative, _crdY.ShowPositive, _crdY.NegativeLimit, _crdY.PositiveLimit);
                    //if (MotionPoints != null && MotionPoints.Count > 0)
                    //{
                    //    for (int i = 0; i < MotionPoints.Count; i++)
                    //    {
                    //        double xBoardPos = _marginLeft;
                    //        double yBoardPos = _marginUp;
                    //        double rBoardPos = 0;
                    //        double rPos2 = 0;
                    //        if (_crdX != null)
                    //            _crdX.GetBoardPosition(MotionPoints[i].OriginPoint[0], _totalWidth, _totalHeight, _marginLeft, _marginUp, _crdX.Direction, out xBoardPos, out rPos2);
                    //        if (_crdY != null)
                    //            _crdY.GetBoardPosition(MotionPoints[i].OriginPoint[1], _totalWidth, _totalHeight, _marginLeft, _marginUp, _crdY.Direction, out yBoardPos, out rPos2);
                    //        if (_crdR != null)
                    //            _crdR.GetBoardPosition(MotionPoints[i].OriginPoint[2], _totalWidth, _totalHeight, _marginLeft, _marginUp, _crdR.Direction, out rBoardPos, out rPos2);
                    //        if (_crdR != null)
                    //            MotionPoints[i].CenterPoint = new PointF((float)rBoardPos, (float)rPos2);
                    //        else
                    //            MotionPoints[i].CenterPoint = new PointF((float)xBoardPos, (float)yBoardPos);
                    //    }
                    //}
                }
            }
            if (_showInfo && !SimpleMode)
            {
                _info.Update( e.X, e.Y, _totalWidth, _totalHeight, _marginLeft, _marginUp, _marginRight, _marginDown, _crdX, _crdY, _crdR);
                this.Repaint();
            }
        }

        bool _showInfo = false;
        private void pB_Displayer_MouseEnter(object sender, EventArgs e)
        {
            _showInfo = true;
        }

        private void pB_Displayer_MouseLeave(object sender, EventArgs e)
        {
            _showInfo = false;
        }

        private void pB_Displayer_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.Clear(_displayerBackColor);
            e.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
            e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;
            e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
            if (this.CreatedShapes != null && this.CreatedShapes.Count > 0)
            {
                for (int i = 0; i < this.CreatedShapes.Count; i++)
                {
                    if (this.CreatedShapes[i].IsShow)
                        this.CreatedShapes[i].Draw(e.Graphics);
                }
            }
            if (MotionPoints != null && MotionPoints.Count > 0)
            {
                for (int i = 0; i < MotionPoints.Count; i++)
                {
                    bool getX = false;
                    bool getY = false;
                    bool getR = false;
                    double xBoardPos = _marginLeft;
                    double yBoardPos = _marginUp;
                    double rBoardPos = 0;
                    double rPos2 = 0;
                    if (_crdX != null)
                        getX = _crdX.GetBoardPosition(MotionPoints[i].OriginPoint[0], _totalWidth, _totalHeight, _marginLeft, _marginUp, _crdX.Direction, out xBoardPos, out rPos2);
                    if (_crdY != null)
                        getY = _crdY.GetBoardPosition(MotionPoints[i].OriginPoint[1], _totalWidth, _totalHeight, _marginLeft, _marginUp, _crdY.Direction, out yBoardPos, out rPos2);
                    if (_crdR != null)
                        getR = _crdR.GetBoardPosition(MotionPoints[i].OriginPoint[2], _totalWidth, _totalHeight, _marginLeft, _marginUp, _crdR.Direction, out rBoardPos, out rPos2);
                    if (_crdR != null)
                        MotionPoints[i].CenterPoint = new PointF((float)rBoardPos, (float)rPos2);
                    else
                    {
                        if ((_crdX != null && _crdY != null) && (!getX || !getY))
                            MotionPoints[i].IsShow = false;
                        else if(_crdX != null && !getX)
                            MotionPoints[i].IsShow = false;
                        else if (_crdY != null && !getY)
                            MotionPoints[i].IsShow = false;
                        else
                        {
                            MotionPoints[i].IsShow = true;
                            MotionPoints[i].CenterPoint = new PointF((float)xBoardPos, (float)yBoardPos);
                        }
                    }
                }
            }
        }

        private void MotionBoard_Resize(object sender, EventArgs e)
        {
            onBoardSizeChanged();
            if (!SimpleMode)
            {
                UpdateBoard();
            }
            else
            {
                updateBoard2();
            }
        }

        private void pB_Displayer_MouseUp(object sender, MouseEventArgs e)
        {
            _startDrag = false;
            if (_crdX != null && _crdY != null)
            {
                foreach (var item in this._directRects)
                {
                    RectDirection dir = item.PointOnDirectionRect(_crdX, _crdY, _crdR, e.X, e.Y);
                    if (dir != RectDirection.Out)
                    {
                        item.Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp);
                        
                    }
                }
                if (rectClicked)
                {
                    if (NotifyDirectRectMouseUp != null)
                        NotifyDirectRectMouseUp(Description);
                }
            }
            if (_crdX == null && _crdY != null)
            {
                foreach (var item in this._directRects)
                {
                    RectDirection dir = item.PointOnDirectionRect(_crdX, _crdY, _crdR, e.X, e.Y);
                    if (dir != RectDirection.Out)
                    {
                        item.Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp);
                        
                    }
                }
                if (rectClicked)
                {
                    if (NotifyDirectRectMouseUp != null)
                        NotifyDirectRectMouseUp(Description);
                }
            }
            if (_crdX != null && _crdY == null)
            {
                foreach (var item in this._directRects)
                {
                    RectDirection dir = item.PointOnDirectionRect(_crdX, _crdY, _crdR, e.X, e.Y);
                    if (dir != RectDirection.Out)
                    {
                        item.Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp);
                    }
                }
                if (rectClicked)
                {
                    if (NotifyDirectRectMouseUp != null)
                        NotifyDirectRectMouseUp(Description);
                }
            }
            if (_crdR != null)
            {
                foreach (var item in this._directRects)
                {
                    RectDirection dir = item.PointOnDirectionRect(_crdX, _crdY, _crdR, e.X, e.Y);
                    if (dir != RectDirection.Out)
                    {
                        item.Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp);
                        
                    }
                }
                if (rectClicked)
                {
                    if (NotifyDirectRectMouseUp != null)
                        NotifyDirectRectMouseUp(Description);
                }
            }
            rectClicked = false;
        }

        private void t_Test_Tick(object sender, EventArgs e)
        {
            
        }

        public async void MoveTable(double x, double y, double r)
        {
            await Task.Factory.StartNew(() =>
            {
                this._table.XPosition = x;
                this._table.YPosition = y;
                this._table.RPosition = r;
                this._table.Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp);
                this.Repaint();
                //for (int i = -50; i < 51; i++)
                //{
                //    this._table.XPosition = i + 100;
                //    this._table.YPosition = Math.Sqrt(2500 - i * i) + 200;
                //    this._table.Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp);
                //    this.Repaint();
                //    System.Threading.Thread.Sleep(10);
                //}
                //for (int i = 50; i > -51; i--)
                //{
                //    this._table.XPosition = i + 100;
                //    this._table.YPosition = -Math.Sqrt(2500 - i * i) + 200;
                //    this._table.Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp);
                //    this.Repaint();
                //    System.Threading.Thread.Sleep(10);
                //}
                //for (int i = 0; i < 180; i++)
                //{
                //    this._table.RPosition = i;
                //    this._table.Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp);
                //    this.Repaint();
                //    System.Threading.Thread.Sleep(10);
                //}
                //for (int i = -180; i < 0; i++)
                //{
                //    this._table.RPosition = i;
                //    this._table.Update(_crdX, _crdY, _crdR, _totalWidth, _totalHeight, _marginLeft, _marginUp);
                //    this.Repaint();
                //    System.Threading.Thread.Sleep(10);
                //}
            });
        }

        public PointF GetShowLimit()
        {
            return new PointF((float)_crdX.ShowNegative, (float)_crdX.ShowPositive);
        }

        public void UpdateInnerRectSizePosition(double showNegativeX, double showPositiveX, 
                                                double NegativeLimitX, double PositiveLimitX,
                                                double showNegativeY, double showPositiveY,
                                                double NegativeLimitY, double PositiveLimitY)
        {
            float width = (float)(((showPositiveX - showNegativeX) / (PositiveLimitX - NegativeLimitX)) * _totalWidth);
            float height = (float)(((showPositiveY - showNegativeY) / (PositiveLimitY - NegativeLimitY)) * _totalHeight);
            float startX = (float)(showNegativeX / (PositiveLimitX - NegativeLimitX) * _totalWidth);
            float startY = (float)(showNegativeY / (PositiveLimitY - NegativeLimitY) * _totalHeight);
            _inRect.StartPoint = new PointF(startX + _marginLeft, startY + _marginUp);
            _inRect.EndPoint = new PointF(startX + _marginLeft + width, startY + _marginUp + height);
        }

        private void MotionBoard_Load(object sender, EventArgs e)
        {
            this.l_Example.Visible = _isDisplayExample;
        }

        private void cMS_Points_Opening(object sender, CancelEventArgs e)
        {
            //cMS_Points.Items.Clear();
            //cMS_Points.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            //        addToolStripItem("移动至此"),
            //        addToolStripItem("移动至设定点")});

        }
        private ToolStripMenuItem addToolStripItem(string text)
        {
            ToolStripMenuItem tsmi = new System.Windows.Forms.ToolStripMenuItem();
            tsmi.Name = text;
            tsmi.Size = new System.Drawing.Size(136, 22);
            tsmi.Text = text;
            tsmi.Click += onToolStripMenuItemClick;
            return tsmi;
        }
        private void onToolStripMenuItemClick(object sender, EventArgs e)
        {
            if ((sender as ToolStripMenuItem).Name.Equals("添加坐标系"))
            {
            }
            else if ((sender as ToolStripMenuItem).Name.Equals("显示"))
            {
            }
            else if ((sender as ToolStripMenuItem).Name.Equals("测试"))
            {
            }
        }

        private void 移动至指定点ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FormPoint pointForm = new FormPoint(_crdX, _crdY, _crdR);
            if(pointForm.ShowDialog() == DialogResult.OK)
            {
                if (OnGoToBoardPoint != null)
                    OnGoToBoardPoint(this, "", pointForm.X, pointForm.Y, pointForm.R);
            }
        }

        private void 移动至此ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            bool isOnPoint = false;
            MotionPoint selectedPoint = null;
            foreach (MotionPoint mp in MotionPoints)
            {
                if (mp.IsSelected)
                {
                    isOnPoint = true;
                    selectedPoint = mp;
                    break;
                }
            }
            if (isOnPoint)
            {
                if (OnGoToBoardPoint != null)
                    OnGoToBoardPoint(this, selectedPoint.Description, selectedPoint.OriginPoint[0], selectedPoint.OriginPoint[1], selectedPoint.OriginPoint[2]);
            }
            else
            {
                if (OnGoToBoardPoint != null)
                    OnGoToBoardPoint(this, "", _curActPosX, _curActPosY, _curActPosR);
            }
        }

        private void 设定当前点位为ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            
        }

        private void 左上ToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        public List<double> GetBoardPosition(double xPos, double yPos, double rPos)
        {
            double posx = _marginLeft;
            double posy = _marginUp;
            double posr1 = 0;
            double posr2 = 0;
            if (_crdX != null)
                _crdX.GetBoardPosition(xPos, _totalWidth, _totalHeight, _marginLeft, _marginUp, _crdX.Direction, out posx, out posr2);
            if (_crdY != null)
                _crdY.GetBoardPosition(yPos, _totalWidth, _totalHeight, _marginLeft, _marginUp, _crdY.Direction, out posy, out posr2);
            if (_crdR != null)
                _crdR.GetBoardPosition(rPos, _totalWidth, _totalHeight, _marginLeft, _marginUp, _crdR.Direction, out posr1, out posr2);
            List<double> pos = new List<double>() { posx, posy, posr1, posr2 };
            return pos;
        }

        private void btn_Stop_Click(object sender, EventArgs e)
        {
            if (NotifyStopClick != null)
                NotifyStopClick(this.Description);
        }
        public void SetXLimit(double posLimit, double negLimit)
        {
            _crdX.NegativeLimit = negLimit;
            _crdX.PositiveLimit = posLimit;
            _crdX.ShowNegative = negLimit;
            _crdX.ShowPositive = posLimit;
        }
        public void SetYLimit(double posLimit, double negLimit)
        {
            _crdY.NegativeLimit = negLimit;
            _crdY.PositiveLimit = posLimit;
            _crdY.ShowNegative = negLimit;
            _crdY.ShowPositive = posLimit;
        }
        public void SetRLimit(double posLimit, double negLimit)
        {
            _crdR.SetPieLimit(negLimit, posLimit);
        }

        private void 键盘移动ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (OnKeyboardEnableClick != null)
                OnKeyboardEnableClick(this);
        }
    }
}
